#include <stdio.h>
#include "EStream.h"
#include "../eCPP.h"

namespace engine
{

//------------------------------------------------------------
EUserStream::EUserStream(const char* filename, bool load) : fp(NULL)
{
  fp = fopen(filename, load ? "rb" : "wb");
}

//------------------------------------------------------------
EUserStream::~EUserStream()
{
  if(fp)	fclose(fp);
}

//------------------------------------------------------------
NxU8 EUserStream::readByte() const
{
  NxU8 b;
  size_t r = fread(&b, sizeof(NxU8), 1, fp);
  NX_ASSERT(r);
  return b;
}

//------------------------------------------------------------
NxU16 EUserStream::readWord() const
{
  NxU16 w;
  size_t r = fread(&w, sizeof(NxU16), 1, fp);
  NX_ASSERT(r);
  return w;
}

//------------------------------------------------------------
NxU32 EUserStream::readDword() const
{
  NxU32 d;
  size_t r = fread(&d, sizeof(NxU32), 1, fp);
  NX_ASSERT(r);
  return d;
}

//------------------------------------------------------------
float EUserStream::readFloat() const
	{
	NxReal f;
	size_t r = fread(&f, sizeof(NxReal), 1, fp);
	NX_ASSERT(r);
	return f;
	}

//------------------------------------------------------------
double EUserStream::readDouble() const
	{
	NxF64 f;
	size_t r = fread(&f, sizeof(NxF64), 1, fp);
	NX_ASSERT(r);
	return f;
	}

//------------------------------------------------------------
void EUserStream::readBuffer(void* buffer, NxU32 size)	const
	{
	size_t w = fread(buffer, size, 1, fp);
	NX_ASSERT(w);
	}

//------------------------------------------------------------
NxStream& EUserStream::storeByte(NxU8 b)
	{
	size_t w = fwrite(&b, sizeof(NxU8), 1, fp);
	NX_ASSERT(w);
	return *this;
	}

//------------------------------------------------------------
NxStream& EUserStream::storeWord(NxU16 w)
	{
	size_t ww = fwrite(&w, sizeof(NxU16), 1, fp);
	NX_ASSERT(ww);
	return *this;
	}

//------------------------------------------------------------
NxStream& EUserStream::storeDword(NxU32 d)
	{
	size_t w = fwrite(&d, sizeof(NxU32), 1, fp);
	NX_ASSERT(w);
	return *this;
	}

//------------------------------------------------------------
NxStream& EUserStream::storeFloat(NxReal f)
	{
	size_t w = fwrite(&f, sizeof(NxReal), 1, fp);
	NX_ASSERT(w);
	return *this;
	}

//------------------------------------------------------------
NxStream& EUserStream::storeDouble(NxF64 f)
	{
	size_t w = fwrite(&f, sizeof(NxF64), 1, fp);
	NX_ASSERT(w);
	return *this;
	}

//------------------------------------------------------------
NxStream& EUserStream::storeBuffer(const void* buffer, NxU32 size)
	{
	size_t w = fwrite(buffer, size, 1, fp);
	NX_ASSERT(w);
	return *this;
	}




//------------------------------------------------------------
EMemoryWriteBuffer::EMemoryWriteBuffer() : currentSize(0), maxSize(0), data(NULL)
	{
	}

//------------------------------------------------------------
EMemoryWriteBuffer::~EMemoryWriteBuffer()
	{
	NX_DELETE_ARRAY(data);
	}

//------------------------------------------------------------
void EMemoryWriteBuffer::clear()
	{
	currentSize = 0;
	}

//------------------------------------------------------------
NxStream& EMemoryWriteBuffer::storeByte(NxU8 b)
	{
	storeBuffer(&b, sizeof(NxU8));
	return *this;
	}

//------------------------------------------------------------
NxStream& EMemoryWriteBuffer::storeWord(NxU16 w)
	{
	storeBuffer(&w, sizeof(NxU16));
	return *this;
	}

//------------------------------------------------------------
NxStream& EMemoryWriteBuffer::storeDword(NxU32 d)
	{
	storeBuffer(&d, sizeof(NxU32));
	return *this;
	}

//------------------------------------------------------------
NxStream& EMemoryWriteBuffer::storeFloat(NxReal f)
	{
	storeBuffer(&f, sizeof(NxReal));
	return *this;
	}

//------------------------------------------------------------
NxStream& EMemoryWriteBuffer::storeDouble(NxF64 f)
	{
	storeBuffer(&f, sizeof(NxF64));
	return *this;
	}

//------------------------------------------------------------
NxStream& EMemoryWriteBuffer::storeBuffer(const void* buffer, NxU32 size)
	{
	NxU32 expectedSize = currentSize + size;
	if(expectedSize > maxSize)
		{
		maxSize = expectedSize + 4096;

		NxU8* newData = new NxU8[maxSize];
		NX_ASSERT(newData!=NULL);

		if(data)
			{
			memcpy(newData, data, currentSize);
			delete[] data;
			}
		data = newData;
		}
	memcpy(data+currentSize, buffer, size);
	currentSize += size;
	return *this;
	}


//------------------------------------------------------------
EMemoryReadBuffer::EMemoryReadBuffer(const NxU8* data) : buffer(data)
	{
	}

//------------------------------------------------------------
EMemoryReadBuffer::~EMemoryReadBuffer()
	{
	// We don't own the data => no delete
	}

//------------------------------------------------------------
NxU8 EMemoryReadBuffer::readByte() const
	{
	NxU8 b;
	memcpy(&b, buffer, sizeof(NxU8));
	buffer += sizeof(NxU8);
	return b;
	}

//------------------------------------------------------------
NxU16 EMemoryReadBuffer::readWord() const
	{
	NxU16 w;
	memcpy(&w, buffer, sizeof(NxU16));
	buffer += sizeof(NxU16);
	return w;
	}

//------------------------------------------------------------
NxU32 EMemoryReadBuffer::readDword() const
	{
	NxU32 d;
	memcpy(&d, buffer, sizeof(NxU32));
	buffer += sizeof(NxU32);
	return d;
	}

//------------------------------------------------------------
float EMemoryReadBuffer::readFloat() const
	{
	float f;
	memcpy(&f, buffer, sizeof(float));
	buffer += sizeof(float);
	return f;
	}

//------------------------------------------------------------
double EMemoryReadBuffer::readDouble() const
	{
	double f;
	memcpy(&f, buffer, sizeof(double));
	buffer += sizeof(double);
	return f;
	}

//------------------------------------------------------------
void EMemoryReadBuffer::readBuffer(void* dest, NxU32 size) const
{
  memcpy(dest, buffer, size);
  buffer += size;
}


} // end namespace
